package com.hrj.file.controller;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.hrj.file.domain.po.FilePo;
import com.hrj.file.domain.po.FolderPo;
import com.hrj.file.domain.vo.ResponseObjectVo;
import com.hrj.file.service.FileService;
import com.hrj.file.service.FolderService;
import com.hrj.file.task.UploadTask;
import com.hrj.file.util.CalculationUtil;
import com.hrj.file.util.MinioUtils;
import io.minio.messages.Upload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.ExecutorService;

@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {

    @Autowired
    public FileService fileSerivce;
    @Autowired
    private FolderService folderService;

    @Value("${minio.fms}")
    private String bucketName;

    @Value("${minio.endpoint}")
    private String endpoint;

    @Autowired
    @Qualifier("threadPoolExecutor")
    private ExecutorService threadPoolExecutor;

    /**
     * 查询文件
     */
    @GetMapping("/list")
    public ResponseObjectVo list(FilePo filePo){
        List<FilePo> filePos = fileSerivce.list(filePo);
        return ResponseObjectVo.success(filePos);
    }


    /**
     * 在主目录中上传文件
     */
    @PostMapping("/addOne")
    @Transactional(rollbackFor = Exception.class)
    public ResponseObjectVo addOne(@RequestPart(value = "multipartFile",required = false) MultipartFile multipartFile){
        String fileName = multipartFile.getOriginalFilename();
        //设置文件code uuid + 文件后缀
        String splitStr [] = fileName.split("\\.");
        String code = UUID.randomUUID().toString().replaceAll("-", "") + "." + splitStr[splitStr.length - 1];
        FolderPo folderPo = new FolderPo();
        folderPo.setFolderName(fileName);
        folderPo.setType(1);
        folderPo.setCreateTime(new Date());
        folderService.save(folderPo);
        FilePo filePo = new FilePo();
        filePo.setFolderId(folderPo.getId());
        filePo.setType(splitStr[splitStr.length - 1]);
        //设置文件名
        filePo.setFileName(fileName);
        //云存储中文件名
        filePo.setStorageFileName(code);
        //设置路径
        filePo.setFileUrl(endpoint+"/"+bucketName+"/"+code);
        //设置创建时间
        filePo.setCreateTime(new Date());
        //设置文件大小
        filePo.setSize(getMB(multipartFile.getSize()));
        //插入文件信息
        fileSerivce.save(filePo);
        try {
            MinioUtils.putObject(bucketName,multipartFile,code);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("msg",fileName);
        objectObjectHashMap.put("id",folderPo.getId());
        return ResponseObjectVo.success(objectObjectHashMap);
    }

    /**
     * 批量上传文件
     * @param id 文件夹id
     */
    @PostMapping("/addBatch")
    @Transactional(rollbackFor = Exception.class)
    public ResponseObjectVo addBatch(@RequestPart(value = "multipartFile",required = false) MultipartFile[] multipartFile,
                                     @RequestParam("id") Long id){
        List<FilePo> filePos = new ArrayList<>();
        for (MultipartFile file : multipartFile) {
            String fileName = file.getOriginalFilename();
            //设置文件code uuid + 文件后缀
            String splitStr [] = fileName.split("\\.");
            String code = UUID.randomUUID().toString().replaceAll("-", "") + "." + splitStr[splitStr.length - 1];
            FilePo filePo = new FilePo();
            filePo.setFolderId(id);
            filePo.setType(splitStr[splitStr.length - 1]);
            //设置文件名
            filePo.setFileName(fileName);
            //云存储中文件名
            filePo.setStorageFileName(code);
            //设置路径
            filePo.setFileUrl(endpoint+"/"+bucketName+"/"+code);
            //设置创建时间
            filePo.setCreateTime(new Date());
            //设置文件大小
            filePo.setSize(getMB(file.getSize()));
            filePos.add(filePo);
            //开线程上传 （目前没做日志）
            threadPoolExecutor.submit(new UploadTask(bucketName,file,code));
        }
        //插入文件信息
        fileSerivce.saveBatch(filePos);
        return ResponseObjectVo.success();
    }

    /**
     * 重命名
     */
    @GetMapping("/rename/{id}/{name}")
    public ResponseObjectVo rename(@PathVariable Long id,@PathVariable String name){
        boolean update = fileSerivce.update(new LambdaUpdateWrapper<FilePo>()
                .eq(FilePo::getId, id)
                .set(FilePo::getFileName, name));
        return update == true ? ResponseObjectVo.success() : ResponseObjectVo.success();
    }

    /**
     * 删除文件
     */
    @GetMapping("/del/{id}")
    public ResponseObjectVo del(@PathVariable Long id){
        //查询云存储中文件名
        FilePo byId = fileSerivce.getById(id);
        try {
            MinioUtils.removeObject(bucketName,byId.getStorageFileName());
            fileSerivce.removeById(id);
        } catch (Exception e) {
            throw new RuntimeException("删除文件失败请重试！");
        }
        return ResponseObjectVo.success();
    }
    /**
     * 计算文件大小MB
     *
     * @param lenth 文件字节长度
     * @return 结果 MB
     */
    private String getMB(Long lenth) {
        return CalculationUtil.getCalculationUtil(CalculationUtil.getCalculationUtil(lenth, 1024, 3).divide(), 1024, 3).divide();
    }
}
